/**
 * Copyright (C) 2017 - 2020 https://github.com/joewee
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bifrost.config;

import com.bifrost.entity.Order;
import com.bifrost.exception.InventoryUnavailableException;
import com.bifrost.workflow.*;
import com.bifrost.workflow.checkout.*;
import com.bifrost.workflow.order.OrderProcessContextFactory;
import com.bifrost.workflow.order.RewardsBonusPointsActivity;
import com.bifrost.workflow.price.*;
import com.bifrost.workflow.price.ValidateProductOptionsActivity;
import org.hibernate.exception.LockAcquisitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author joewee
 * @version 1.0.0
 * @Date 2017/11/14 19:23
 */
@Configuration
public class WorkflowConfig {
    @Resource
    PricingProcessContextFactory pricingProcessContextFactory;
    @Resource
    DefaultErrorHandler defaultErrorHandler;
    @Resource
    ItemActivity itemActivity;
    @Resource
    ServiceActivity serviceActivity;
    @Resource
    ShippingActivity shippingActivity;
    @Resource
    ShippingOfferActivity shippingOfferActivity;
    @Resource
    CouponActivity couponActivity;
    @Resource
    BonusPointsActivity bonusPointsActivity;
    @Resource
    TotalActivity totalActivity;
    @Resource
    ValidateProductOptionsActivity validateProductOptionsActivity;
    /**
     * checkout workflow
     */
    @Resource
    CheckoutProcessContextFactory checkoutProcessContextFactory;
    @Resource
    ValidateCheckoutActivity validateCheckoutActivity;
    @Resource
    VerifyCustomerMaxOfferUsesActivity verifyCustomerMaxOfferUsesActivity;
    @Resource
    ValidateAndConfirmPaymentActivity validateAndConfirmPaymentActivity;
    @Resource
    RecordOfferUsageActivity recordOfferUsageActivity;
    @Resource
    DecrementInventoryActivity decrementInventoryActivity;
    @Resource
    CompleteOrderActivity completeOrderActivity;
    @Resource
    UseBonusPointsUsageActivity useBonusPointsUsageActivity;
    /**
     * order workflow
     * */
    @Resource
    OrderProcessContextFactory orderProcessContextFactory;
    @Resource
    RewardsBonusPointsActivity rewardsBonusPointsActivity;
@Bean("completeOrderActivity")
@ConditionalOnMissingBean
public CompleteOrderActivity getCompleteOrderActivity(@Qualifier("completeOrderRollbackHandler") CompleteOrderRollbackHandler rollbackHandler){
    return new CompleteOrderActivity(rollbackHandler);
}

    @Bean(name = "pricingWorkflow")
    public SequenceProcessor getPricingWorkflow() {
        SequenceProcessor sequenceProcessor = new SequenceProcessor();
        sequenceProcessor.setProcessContextFactory(pricingProcessContextFactory);
        //ListFactoryBean pricingWorkflowActivities =new ListFactoryBean();
        List<Activity<ProcessContext<Order>>> activities = new ArrayList<>();
        activities.add(itemActivity);
        activities.add(serviceActivity);
        activities.add(shippingActivity);
        activities.add(shippingOfferActivity);
        activities.add(couponActivity);
        activities.add(bonusPointsActivity);
        activities.add(totalActivity);
        activities.add(validateProductOptionsActivity);
        //pricingWorkflowActivities.setSourceList(activities);
        sequenceProcessor.setActivities(activities);
        List<String> classes = new ArrayList<>();
        classes.add(LockAcquisitionException.class.getName());
        defaultErrorHandler.setUnloggedExceptionClasses(classes);
        sequenceProcessor.setDefaultErrorHandler(defaultErrorHandler);
        return sequenceProcessor;
    }

    @Bean(name = "checkoutWorkflow")
    public Processor<CheckoutSeed, CheckoutSeed> getCheckoutWorkflow() {
        SequenceProcessor sequenceProcessor = new SequenceProcessor();
        sequenceProcessor.setProcessContextFactory(checkoutProcessContextFactory);
        List<Activity> activities = new ArrayList<>();
        activities.add(validateCheckoutActivity);
        activities.add(verifyCustomerMaxOfferUsesActivity);
        activities.add(validateAndConfirmPaymentActivity);
        activities.add(recordOfferUsageActivity);
        activities.add(useBonusPointsUsageActivity);
        activities.add(decrementInventoryActivity);
        activities.add(completeOrderActivity);
        sequenceProcessor.setActivities(activities);
        List<String> classes = new ArrayList<>();
        classes.add(InventoryUnavailableException.class.getName());
        defaultErrorHandler.setUnloggedExceptionClasses(classes);
        sequenceProcessor.setDefaultErrorHandler(defaultErrorHandler);
        return sequenceProcessor;
    }
    @Bean(name ="orderWorkflow")
    public SequenceProcessor getOrderWorkflow(){
        SequenceProcessor sequenceProcessor = new SequenceProcessor();
        sequenceProcessor.setProcessContextFactory(orderProcessContextFactory);
        List<Activity<ProcessContext<Order>>> activities = new ArrayList<>();
        activities.add(rewardsBonusPointsActivity);
        sequenceProcessor.setActivities(activities);
        List<String> classes = new ArrayList<>();
        classes.add(LockAcquisitionException.class.getName());
        defaultErrorHandler.setUnloggedExceptionClasses(classes);
        sequenceProcessor.setDefaultErrorHandler(defaultErrorHandler);
        return sequenceProcessor;
    }
}
